package com.chs.springai_alibaba.Controller;

import com.alibaba.cloud.ai.advisor.DocumentRetrievalAdvisor;
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel;
import com.alibaba.cloud.ai.dashscope.rag.*;
import com.chs.springai_alibaba.service.RAGService;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.document.Document;
import org.springframework.ai.document.DocumentRetriever;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;

@RestController
public class ChatGptController
{

    private final ChatClient chatClient;
    //对话记忆对象
    ChatMemory chatMemory = new InMemoryChatMemory();
    //对话记忆的唯一标识
    String conversantId = UUID.randomUUID().toString();
    //初始化ChatClient
    public ChatGptController(ChatClient.Builder builder, VectorStore vectorStore) {
        this.chatClient = builder.defaultSystem("""
                        您是 “地铁出行小助手”。请以热情、耐心且专业的方式来回复。
                        您正在通过智能交互系统与乘客互动。
                        在询问用户之前，请检查消息历史记录以获取此信息。
                        在处理如退票等涉及票务规则变更的操作之前，您必须确保相关地铁票务条款允许这样做。
                        如果操作涉及费用产生（如某些特殊票务处理可能有手续费等情况），您必须在继续之前征得用户同意。
                        使用提供的功能获取地铁运营详细信息（如各线路实时运行状况、首末班车时间等）、
                        进行票务相关操作（如购票、查询余额等）以及查询车站设施详情（如电梯位置、洗手间分布等）。
                        如果需要，可以调用相应函数调用完成辅助动作。""") //人设信息
                .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory),//对话记忆
                        new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults())) //RAG
                .build();
    }

    /**
     * 流式API
     */
    @RequestMapping(value = "/ai/stream",produces = "text/html;charset=utf-8")
    public Flux<String> fluxChat(@RequestParam("message")String message) {
        return chatClient.prompt().user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, conversantId)
                .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10)) //对话记忆
                .stream().content();
    }
}
